/**
 * Copyright (C) 2010 David Simonek <dafesimonek@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.dafe.partyband.importer.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.dafe.partyband.importer.api.IDirectoryScanner;
import org.dafe.partyband.importer.api.INameEncoder;
import org.dafe.partyband.importer.api.IScanResult;

/**
 *
 * @author dafe
 */
public class DirectoryScanner implements IDirectoryScanner {

    private static final String delimExp = "[-,_:;\" ]";

    private INameEncoder encoder;
    private File dir;

    public IScanResult scan() {
        assert encoder != null : "Need name encoder";
        assert dir != null : "Need directory to scan";

        ScanResult result = new ScanResult();
        Map<String, String> encoded2Names = new HashMap<String, String>();
        Queue<File> fileQueue = new LinkedList<File>();
        fileQueue.add(dir);

        while (!fileQueue.isEmpty()) {
            File curFile = fileQueue.poll();

            if (curFile.isDirectory()) {
                File[] children = curFile.listFiles();
                if (children != null) {
                    fileQueue.addAll(Arrays.asList(children));
                } else {
                    System.out.println("NULL voe...: " + curFile.toString());
                }
            } else if (curFile.isFile() && !curFile.isHidden()) {
                String fileName = curFile.getName();
                int index = fileName.indexOf('.');
                String name = index >=0 ? fileName.substring(0, index) : fileName;
                String encodedName = encoder.encodeName(name);
                String storedName = encoded2Names.get(encodedName);
                if (storedName == null) {
                    result.addSongName(name);
                    result.addFile(name, curFile);
                    encoded2Names.put(encodedName, name);
                } else {
                    Set<File> storedFiles = result.getFiles(storedName);
                    boolean alreadyThere = false;
                    for (File file : storedFiles) {
                        if (curFile.getName().equals(file.getName())) {
                            alreadyThere = true;
                            break;
                        }
                    }
                    if (!alreadyThere) {
                        result.addFile(storedName, curFile);
                    }
                }
            }
        }

        return result;
    }

    public void setDirectory(File dir) {
        this.dir = dir;
    }

    public void setEncoder(INameEncoder encoder) {
        this.encoder = encoder;
    }

    public INameEncoder getEncoder() {
        return encoder;
    }

    public List<File> findSimilar(String songName) {
        assert encoder != null : "Need name encoder";
        assert dir != null : "Need directory to scan";
        
        List<File> result = new ArrayList<File>();
        Queue<File> fileQueue = new LinkedList<File>();
        fileQueue.add(dir);

        while (!fileQueue.isEmpty()) {
            File curFile = fileQueue.poll();

            if (curFile.isDirectory()) {
                File[] children = curFile.listFiles();
                if (children != null) {
                    fileQueue.addAll(Arrays.asList(children));
                }
            } else if (curFile.isFile() && !curFile.isHidden()) {
                String fileName = curFile.getName();
                int index = fileName.indexOf('.');
                String name = index >=0 ? fileName.substring(0, index) : fileName;
                if (isSimilar(songName, name)) {
                    result.add(curFile);
                }
            }
        }
        return result;
    }

    private boolean isSimilar (String songName, String resourceName) {
        String[] songNameWords = songName.split(delimExp);
        String[] resourceWords = resourceName.split(delimExp);
        for (int j = 0; j < songNameWords.length; j++) {
            String songWord = encoder.encodeName(songNameWords[j]);
            for (int i = 0; i < resourceWords.length; i++) {
                String resourceWord = encoder.encodeName(resourceWords[i]);
                if (resourceWord.length() > 3 && songWord.equalsIgnoreCase(resourceWord)) {
                    return true;
                }
            }
        }

        return false;
    }

}
